#ifndef __MULTILEVEL__
#define __MULTILEVEL__

#include "assemble.h"

typedef struct MULTILEVEL_
{
    /* 设置 */
    DATATYPE datatype;

    /* 属性 */
    INT num_levels;

    /* 记录 */
    FEMSPACE *femspace; // 当前有限元空间

    /* 数据 */
    // 每层网格储存一个刚度矩阵和质量矩阵(线性部分) 这样在扩展子空间校正的时候就不需要重新计算线性部分了
    MATRIX **stiff_matrices; // 刚度矩阵
    MATRIX **mass_matrices;  // 质量矩阵
    MATRIX **prolongs;       // 插值矩阵
    MATRIX **restricts;      // 限制矩阵
    VECTOR **solution;       // 解
    VECTOR **rhs;            // 右端项
    INT num_eig;             // 特征对的个数
    DOUBLE *eigvalues;       // 特征值
    VECTORS **eigvecs;       // 特征向量
} MULTILEVEL;

void MultiLevelCreate(MULTILEVEL **multilevel, DATATYPE type);
void MultiLevelDestroy(MULTILEVEL **multilevel);
void MultiLevelOutput(MULTILEVEL *multilevel, const char *name);


// 给multilevel添加一层, 会根据stiff_discreteform和mass_discreteform生成刚度矩阵和质量矩阵, NULL代表不生成该项
void MultiLevelAddLevel(MULTILEVEL *multilevel, DISCRETEFORM *stiff_discreteform, DISCRETEFORM *mass_discreteform);
// 给multilevel添加一层, 但只产生插值矩阵
void MultiLevelAddLevelSimple(MULTILEVEL *multilevel, FEMSPACE *newspace);
// 给multilevel指定层设置各类数据，可以和上面的程序结合使用
void MultiLevelSetMatrix(MULTILEVEL *multilevel, MATRIX *stiff_matrix, MATRIX *mass_matrix, INT target_level);
void MultiLevelSetVector(MULTILEVEL *multilevel, VECTOR *Rhs, VECTOR *solution, INT target_level);
void MultiLevelSetNev(MULTILEVEL *multilevel, INT nev);


#endif